#include <iostream>
#include <sys/ipc.h> //ftok
#include <sys/shm.h>
#include <unistd.h>
#include <cstdio>
#include <string>
#include <cstring>

#include"named_pipe.hpp"

#define PATH_NAME "."
#define PRO_ID 1

#define SERVER IPC_CREAT|IPC_EXCL|0666
#define CLIENT IPC_CREAT

#define VM_SIZE 4096

#define CREATOR "creator"
#define USER "user"


class Shm
{
    void CreateHelper(int flag)
    {
        _key = ftok(_pathname.c_str(),_proid);
        if(_key < 0)
            ERR_INFO("ftok");
        
        _shmid = shmget(_key,VM_SIZE,flag);
        if(_shmid < 0)
            ERR_INFO("shmget");
    }
    void Create()
    {
        CreateHelper(SERVER);
    }
    void Get()
    {
        CreateHelper(CLIENT);
    }
    void Attach()
    {
        _address = shmat(_shmid,nullptr,0);
    }
    void Detach()
    {
        int ret = shmdt(_address);
        if(ret < 0)
            ERR_INFO("shmdt");
    }
    void Delete()
    {
        int ret = shmctl(_shmid,IPC_RMID,nullptr);
        if(ret < 0 )
            ERR_INFO("shmctl");
    }
public:
    Shm(std::string username , std::string pathname , int proid)
    :_username(username),_pathname(pathname),_proid(proid)
    {
        if(_username == CREATOR)
        {
            Create();
        }
        else
        {
            Get();
        }
        Attach();
    }
    void* Ptr()
    {
        return _address;
    }
    ~Shm()
    {
        Detach();
        Delete();
    }
private:
    std::string _username;
    std::string _pathname;
    int _proid;
    key_t _key;
    int _shmid;
    void* _address = nullptr;
};
// class Shm
// {
// private:
//     void Allocate(int option)
//     {
//         _key = ftok(PATH_NAME, PRO_ID);
//         if (_key < 0)
//             ERR_INFO("ftok");

//         _shmId = shmget(_key, _capacity, option);
//         _address = shmat(_shmId, nullptr, 0);
//         if(_address == (void*)-1)
//             ERR_INFO("shmat");
//     }

// public:
//     Shm(int identity, int size = 0, int capacity = 4096, int offset_read = 0, int offset_write = 0)
//         : _identity(identity),
//           _size(size),
//           _capacity(capacity),
//           _offset_read(offset_read),
//           _offset_write(offset_write)
//     {
//         Allocate(_identity);
//     }

//     void Write()
//     {
//         std::string st;
//         std::getline(std::cin, st);
//         memcpy(((char *)_address) + _offset_write, st.c_str(), st.size()+1);
//         _offset_write += st.size();
//         _size += st.size();
//     }
//     void Read()
//     {
//         char* ad = (char*)_address;
//         printf("%s\n", ad);
//     }
//     ~Shm()
//     {
//         if (_identity == SERVER)
//         {
//             int ret = shmdt(_address);
//             if (ret < 0)
//             {
//                 ERR_INFO("shmdt");
//             }
//             shmctl(_shmId, IPC_RMID, nullptr);
//         }
//     }

// private:
//     key_t _key = -1;
//     int _identity;
//     int _shmId;
//     size_t _capacity;
//     size_t _size;
//     void *_address;
//     int _offset_read;
//     int _offset_write;
// };
